/**
 * Author:  LiShibin.
 * Date:    2016/9/9.
 * File：   .
 */
import EXIF from './assets/dep/exif'

/**
 * 深拷贝
 * @param {Object} 被复制的对象
 * @param {Object} 目标对象,默认为空对象
 * @return {Object}}
 */
function clone(obj, target) {
  target = target || {}
  for (var i in obj) {
    if (obj[i] && typeof obj[i] === 'object') {
      target[i] = (obj[i].constructor === Array) ? [] : {}
      exports.clone(obj[i], target[i])
    } else {
      target[i] = obj[i]
    }
  }
  return target
}
/**
 * 从数组中移除一个对象
 * @param arr 数组对象
 * @param field 移除的字段匹配
 * @param text 匹配的值
 * @return {Boolean}
 */
function arrayRemoveOne(arr, field, text) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][field] === text) {
      arr.splice(i, 1)
      return true
    }
  }
  return false
}

/**
 * 判断对象是否为空对象
 * @param e 判断对象
 * @returns {boolean}
 */
function isEmptyObject(e) {
  // vue 框架给数组添加了一个$remove的方法，所以对数组单独判断
  if (e instanceof Array) {
    if (e.length > 0) {
      return false
    } else {
      return true
    }
  }
  for (var t in e) {
    return false
  }
  return true
}

/**
 * 触发点击事件
 * @param element
 */
function clickFileInput(element) {
  element.click()
  let deviceType = exports.getDeviceType()
  if (deviceType == 'wx-iPhone' || deviceType == 'iPhone') {
    // 对于 input type='file' 控件 ios需要再触发click才能生效
    element.click()
  }
}

/**
 * 锁定
 * @param element 要锁定的dom
 * @param timeOut 锁定时间，默认1秒
 * @return {boolean} 是否在锁定状态中
 */
function freeze(element, timeOut) {
  timeOut = timeOut || 1000
  if (typeof element === 'string') {
    element = document.getElementById(element)
  }
  let freezeFlag = element.getAttribute('freeze-flag') // 是否锁定中
  let freezeFlagCountdown = element.getAttribute('freeze-flag-countdown') // 是否已经开始倒计时解锁中
  if (freezeFlag) {
    if (!freezeFlagCountdown) {
      element.setAttribute('freeze-flag-countdown', 'true') // 开始倒计时
      setTimeout(() => { // 倒计时结束
        element.removeAttribute('freeze-flag-countdown')
        element.removeAttribute('freeze-flag')
      }, timeOut)
    }
    return true
  } else {
    element.setAttribute('freeze-flag', 'true')
    element.removeAttribute('freeze-flag-countdown')
    return false
  }
}
/**
 * 获取设备类型
 * @return string 'Android'or'iPhone' or 'iPad' or'Windows'or'unknown' or 'weixin'
 */
function getDeviceType() {
  var agent = navigator.userAgent
  var device = ''
  if (agent.indexOf('MicroMessenger') !== -1 && agent.indexOf('Android') !== -1) {
    device = 'wx-Android'
  } else if (agent.indexOf('MicroMessenger') !== -1 && agent.indexOf('iPhone') !== -1) {
    device = 'wx-iPhone'
  } else if (agent.indexOf('Android') !== -1) {
    device = 'Android'
  } else if (agent.indexOf('iPhone') !== -1) {
    device = 'iPhone'
  } else if (agent.indexOf('iPad') !== -1) {
    device = 'iPad'
  } else if (agent.indexOf('Windows') !== -1) {
    device = 'Windows'
  } else {
    device = 'unknown'
  }
  return device
}
/**
 * 压缩图片
 * @param file 图片文件
 * @callBack 压缩完成后的回调函数，参数：(base64)
 */
function compress(file, callBack, compressRate, maxWidth) {
  var img = new window.Image()
  // 压缩比
  compressRate = compressRate || 0.6
  // 最大宽度
  maxWidth = maxWidth || 640

  img.onload = function () {
    var cvs = document.createElement('canvas')
    var ctx = cvs.getContext('2d')

    if (img.width > maxWidth) {
      img.height *= maxWidth / img.width
      img.width = maxWidth
    }
    cvs.width = img.width
    cvs.height = img.height
    ctx.clearRect(0, 0, cvs.width, cvs.height)
    ctx.drawImage(img, 0, 0, img.width, img.height)

    var dataUrl = cvs.toDataURL('image/jpeg', compressRate)
    if (typeof callBack === 'function') {
      callBack(dataUrl)
    }
  }

  img.src = file
}
/**
 * 旋转并压缩图片(旋转至正确方向)
 * @param file 图片文件
 * @param fileSize 图片文件的大小
 * @callBack 压缩完成后的回调函数，参数：(base64)
 */
function compressAndRotate(file, callBack, compressRate, square) {
  var img = new window.Image()
  // 压缩比
  compressRate = compressRate || 0.6
  square = square || 640 // 画布大小的基数
  img.onload = function () {
    EXIF.getData(img, function () {
      console.log('获取到图片exif信息')
      var orientation = EXIF.getTag(this, 'Orientation') // 获取图片方向
      var canvas = document.createElement('canvas')
      var num = 0
      var imageHeight = square
      var imageWidth = Math.round(square * img.width / img.height)
      canvas.height = imageHeight
      canvas.width = imageWidth
      if (orientation == 6) { // 顺时针90°
        num = 90
      } else if (orientation == 3) { // 180°
        num = 180
      } else if (orientation == 8) { // 逆时针90°
        num = 270
      }
      if (num == 360) {
        num = 0
      }
      var ctx = canvas.getContext('2d')
      ctx.translate(imageWidth / 2, imageHeight / 2)
      ctx.rotate(num * Math.PI / 180)
      ctx.translate(-imageWidth / 2, -imageHeight / 2)
      ctx.drawImage(img, 0, 0, imageWidth, imageHeight)
      var dataUrl = canvas.toDataURL('image/jpeg', compressRate)
      if (typeof callBack == 'function') {
        callBack(dataUrl)
      }
    })
  }
  img.src = file
}
/**
 * 冷却，防止快速重复点击
 * @param element 要冷却的节点
 * @param coolingTime 冷却时间（ms），默认为1000(ms)
 */
function coolingElement(element, coolingTime) {
  coolingTime = coolingTime || 1000
  if (typeof element === 'string') {
    element = document.getElementById(element)
  }
  element.disabled = true
  setTimeout(function () {
    element.disabled = false
  }, coolingTime)
}

/**
 * 初始化百度地图对象
 * @param key 百度密钥
 * @returns {Promise} 异步对象
 */
function initMap(key) {
  return new Promise((resolve, reject) => {
    if (document.getElementById('baiduMap')) {
      resolve(window.BMap)
      return
    }
    var script = document.createElement('script')
    script.id = 'baiduMap'
    script.type = 'text/javascript'
    script.src = 'http://api.map.baidu.com/getscript?v=2.0&ak=' + key + '&services=&t=' + (new Date).getTime()
    script.onload = (event) => {
      resolve(window.BMap)
    }
    script.onerror = (error) => {
      reject(error)
    }
    document.head.appendChild(script)
  })
}
/**
 * 直接获取定位对象
 * @returns {Promise}
 */
function getLocal() {
  return new Promise((resolve, reject) => {
    exports.initMap('tzAcIFZ5xCoRwm63NcBGfoVB').then(BMap => {
      var getLocation = new BMap.Geolocation()
      var geocoder = new BMap.Geocoder()
      getLocation.getCurrentPosition(function (cp) {
        geocoder.getLocation(cp.point, function (cl) {
          var options = cl.addressComponents
          options.point = cl.point
          resolve(options)
        })
      }, function (e) {
        console.error('getCurrentPosition失败：', e)
      })
    }, e => {
      console.error('initMap失败：', e)
    })
  })
}
/**
 * 字符串转bool
 * @param str
 * @returns {boolean}
 */
function strToBool(str) {
  if (typeof str === 'boolean') {
    return str
  } else if (typeof str === 'string') {
    return str === 'true'
  } else {
    return false
  }
}

function getNowFormatDate() {
  var date = new Date()
  var seperator1 = '-'
  var seperator2 = ':'
  var year = date.getFullYear()
  var month = date.getMonth() + 1
  var strDate = date.getDate()
  var hour = date.getHours()
  var minute = date.getMinutes()
  var second = date.getSeconds()

  if (month >= 1 && month <= 9) {
    month = '0' + month
  }
  if (strDate >= 0 && strDate <= 9) {
    strDate = '0' + strDate
  }
  if (hour >= 0 && hour <= 9) {
    hour = '0' + hour
  }
  if (minute >= 0 && minute <= 9) {
    minute = '0' + minute
  }
  if (second >= 0 && second <= 9) {
    second = '0' + second
  }
  var currentdate = year + seperator1 + month + seperator1 + strDate + ' ' + hour + seperator2 + minute + seperator2 + second
  return currentdate
}

/**
 * 计算当前时间较发布时间过去了多久，如一周前、一小时前等
 *
 */
function getDateDiff(dateTimeStamp) {
  var result
  var minute = 60
  var hour = minute * 60
  var day = hour * 24
  // var halfamonth = day * 15
  var month = day * 30
  var now = Math.round(new Date().getTime() / 1000)
  var diffValue = now - dateTimeStamp
  if (diffValue < 0) {
    return '刚刚'
  }
  var monthC = diffValue / month
  var weekC = diffValue / (7 * day)
  var dayC = diffValue / day
  var hourC = diffValue / hour
  var minC = diffValue / minute
  if (monthC >= 1) {
    // result = parseInt(monthC) + '个月前'
  } else if (weekC >= 1) {
    result = parseInt(weekC) + '周前'
  } else if (dayC >= 1) {
    result = parseInt(dayC) + '天前'
  } else if (hourC >= 1) {
    result = parseInt(hourC) + '小时前'
  } else if (minC >= 1) {
    result = parseInt(minC) + '分钟前'
  } else {
    result = '刚刚'
  }
  return result
}
/**
 * 计算时间差
 * @param time1 开始时间
 * @param time2 结束时间
 * @returns {{days: number, hours: number, minutes: number, seconds: number}}
 */
function timeDif(time1, time2) {
  if (!(time1 instanceof Date)) {
    time1 = time1.replace(/-/g, function () { // ios 2017-01-01 格式无法做为new Date()的参数，需改为2017/01/02
      return '/'
    })
    time1 = new Date(time1)
  }
  if (!(time2 instanceof Date)) {
    time2 = time2.replace(/-/g, function () { // ios 2017-01-01 格式无法做为new Date()的参数，需改为2017/01/02
      return '/'
    })
    time2 = new Date(time2)
  }
  var dif = time2.getTime() - time1.getTime()  // 时间差的毫秒数
  // 计算出相差天数
  var days = Math.floor(dif / (24 * 3600 * 1000))
  // 计算出小时数
  var leave1 = dif % (24 * 3600 * 1000)    // 计算天数后剩余的毫秒数
  var hours = Math.floor(leave1 / (3600 * 1000))
  // 计算相差分钟数
  var leave2 = leave1 % (3600 * 1000)        // 计算小时数后剩余的毫秒数
  var minutes = Math.floor(leave2 / (60 * 1000))
  // 计算相差秒数
  var leave3 = leave2 % (60 * 1000)      // 计算分钟数后剩余的毫秒数
  var seconds = Math.round(leave3 / 1000)
  return {days: days, hours: hours, minutes: minutes, seconds: seconds}
}
/**
 * 获取剩余时间
 * @param endTimeTamp 截止时间的时间戳
 * @returns {days, hours, minutes, seconds}
 */
function getTimeRemain(endTimeTamp) {
  if (endTimeTamp) {
    let currentTime = new Date()
    let endTime = new Date()
    endTime.setTime(endTimeTamp * 1000)
    return timeDif(currentTime, endTime)
  }
}

// 'yyyy-MM-dd hh:mm:ss
function formatDate(dateObj, format) {
  var date = {
    'M+': dateObj.getMonth() + 1,
    'd+': dateObj.getDate(),
    'h+': dateObj.getHours(),
    'm+': dateObj.getMinutes(),
    's+': dateObj.getSeconds(),
    'q+': Math.floor((dateObj.getMonth() + 3) / 3),
    'S+': dateObj.getMilliseconds()
  }
  if (/(y+)/i.test(format)) {
    format = format.replace(RegExp.$1, (dateObj.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  for (var k in date) {
    if (new RegExp('(' + k + ')').test(format)) {
      format = format.replace(RegExp.$1, RegExp.$1.length === 1
        ? date[k] : ('00' + date[k]).substr(('' + date[k]).length))
    }
  }
  return format
}

// 时间戳转为时间 yyyy-MM-dd hh:mm:ss
function timestampToDate(value, format) {
  if (!value || value == '') {
    return ''
  }
  format = format || 'yyyy-MM-dd hh:mm:ss'
  var date = new Date()
  date.setTime(value * 1000)
  var dateStr = formatDate(date, format)
  return dateStr
}

function getQueryString(name) {
  var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
  var r = window.location.search.substr(1).match(reg)
  if (r != null) {
    return unescape(r[2])
  }
  return ''
}

/***
 * 节流函数 连续调用不会一直触发，只有在等待wait时间后再次调用才会再触发一次
 * @param func 执行函数
 * @param wait 等待时间
 * @param immediate 是否立即执行
 * @return {Function}
 */
function throttle(func, wait, immediate) {
  var timeout
  return function () {
    let context = this
    let args = arguments
    let later = function () {
      timeout = null
      if (!immediate) func.apply(context, args)
    }
    let callNow = immediate && !timeout
    clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func.apply(context, args)
  }
}
/***
 * 节流函数2 连续调用，在每等待wait时间后就触发一次
 * @param func 执行函数
 * @param wait 等待时间
 * @param immediate 是否立即执行
 * @return {Function}
 */
function throttle2(func, wait, immediate) {
  var timeout
  return function () {
    let context = this
    let args = arguments
    let later = function () {
      timeout = null
      if (!immediate) func.apply(context, args)
    }
    let callNow = immediate && !timeout
    if (!timeout) {
      timeout = setTimeout(later, wait)
    }
    if (callNow) func.apply(context, args)
  }
}
function HTMLDecode(text) {
  var temp = document.createElement('div')
  temp.innerHTML = text || ''
  var output = temp.innerText || temp.textContent
  temp = null
  return output
}

function setCookie(name, value, expireHours) {
  var cookieString = name + '=' + escape(value) + '; path=/'
  expireHours = expireHours || 24 * 365 // 默认一年
  // 判断是否设置过期时间
  if (expireHours > 0) {
    var date = new Date()
    date.setTime(date.getTime + expireHours * 3600 * 1000)
    cookieString = cookieString + '; expire=' + date.toGMTString()
  }
  document.cookie = cookieString
}

function getCookie(name) {
  var strcookie = document.cookie
  var arrcookie = strcookie.split('; ')
  for (var i = 0; i < arrcookie.length; i++) {
    var arr = arrcookie[i].split('=')
    if (arr[0] == name) {
      return arr[1]
    }
  }
  return ''
}

// 删除cookie
function delCookie(name) {
  var exp = new Date()
  exp.setTime(exp.getTime() - 1)
  var cval = getCookie(name)
  if (cval != null) document.cookie = name + '=' + cval + '; path=/;expires=' + exp.toGMTString()
}

/**
 * 图片是否加载完成
 * @param url
 * @returns {Promise}
 */
function imgLoaded(url) {
  return new Promise((resolve, reject) => {
    let img = new window.Image()
    img.onload = () => {
      resolve(img)
    }
    img.onerror = () => {
      reject()
    }
    img.src = url
  })
}
/**
 * 检测是否是空值
 * @param value
 * @returns {boolean}
 */
function empty(value) {
  if (!value) {
    return true
  } else {
    if (value == '') {
      return true
    }
    return false
  }
}

function addBodyFix() {
  document.body.style.overflow = 'hidden'
  document.body.style.height = '100%'
  document.getElementsByTagName('html')[0].style.overflow = 'hidden'
  document.getElementsByTagName('html')[0].style.height = '100%'
}
function removeBodyFix() {
  document.body.style.overflow = 'auto'
  document.body.style.height = 'auto'
  document.getElementsByTagName('html')[0].style.overflow = 'auto'
  document.getElementsByTagName('html')[0].style.height = 'auto'
}
function getRandomStr() {
  return Math.random().toString(36).substr(2)
}
function wxGetLocalImgData(localId) {
  return new Promise((resolve, reject) => {
    wx.getLocalImgData({ // eslint-disable-line
      localId: localId,
      success: (res) => {
        var localData = res.localData
        localData = localData.replace('data:image/jgp;base64', 'data:image/jpeg;base64')
        if (localData.indexOf('data:image/jpeg;base64,') == -1) {
          localData = 'data:image/jpeg;base64,' + localData
        }
        resolve(localData)
      },
      fail: (err) => {
        reject(err)
      }
    })
  })
}
// 用Promise封装其他API
function promisify(api) {
  return (options, ...params) => {
    return new Promise((resolve, reject) => {
      api(Object.assign({}, options, {success: resolve, fail: reject}), ...params)
    })
  }
}

function setWechatTitle(title) {
  document.title = title
  let deviceType = getDeviceType()
  if (deviceType == 'wx-Android' || deviceType == 'wx-iPhone') {
    var i = document.createElement('iframe')
    i.src = '/favicon.ico'
    i.style.display = 'none'
    i.onload = function () {
      setTimeout(function () {
        i.remove()
      }, 9)
    }
    document.body.appendChild(i)
  }
}

/**
 * 获取第几天的日期
 * @param day 如：2 两天后的日期， -2 两天前的日期
 * @returns {string}
 */
function getDay(day) {
  var today = new Date()
  var targetday_milliseconds = today.getTime() + 1000 * 60 * 60 * 24 * day
  today.setTime(targetday_milliseconds) // 注意，这行是关键代码
  return today
  // var tYear = today.getFullYear()
  // var tMonth = today.getMonth()
  // var tDate = today.getDate()
  // tMonth = doHandleMonth(tMonth + 1)
  // tDate = doHandleMonth(tDate)
  // return tYear + "-" + tMonth + "-" + tDate
}

export {
  clone,
  arrayRemoveOne,
  isEmptyObject,
  clickFileInput,
  freeze,
  getDeviceType,
  compress,
  compressAndRotate,
  coolingElement,
  initMap,
  getLocal,
  strToBool,
  getNowFormatDate,
  getDateDiff,
  timeDif,
  formatDate,
  getTimeRemain,
  timestampToDate,
  getQueryString,
  throttle,
  throttle2,
  HTMLDecode,
  setCookie,
  getCookie,
  delCookie,
  imgLoaded,
  empty,
  addBodyFix,
  removeBodyFix,
  getRandomStr,
  wxGetLocalImgData,
  promisify,
  setWechatTitle,
  getDay
}
